import {BaseCrash} from "./BaseCrash.js";
import {Log} from "../log/Log.js";
import {Config} from "../config/Config.js";

/**
 * 碰撞检测
 */
export class Crash extends BaseCrash{
    title = '碰撞检测';
    description = '所有碰撞必须加上对象边框宽度、margin、padding，否则不够精确';


    init(){
        Log.log('碰撞组件初始化');



    }


    /**
     * 对象碰撞检测
     *
     * @param element 源元素
     * @param toElements 目标元素(可能是多个)
     * @param callback
     */
    detect(element, toElements, callback){
        Log.log(
            element,
            toElements,
        );

        if(callback && typeof callback != 'function') throw new Error('回调函数类型错误');
        if(!$(element).length) throw new Error('源元素不存在');
        if(!$(toElements).length) throw new Error('目标元素不存在');

        this.crash(element, toElements, callback);
    }


    /**
     * 顶部碰撞
     * @param element 源元素
     * @param toElement 目标元素(单个)
     * @param callback
     */
    _detectTop(element, toElement, callback){


        if(this.getTop(element) + this.getAllHeight(element) >= this.getTop(toElement)){
            Log.log('碰撞生效');

            return callback?callback():false;
        }


    }

    /**
     * 边界碰撞
     * 使用场景：以容器为边界时调用
     * @param element
     * @param callback
     * @returns {boolean}
     */
    detectContainer(element, callback){
        let that = this;
        Log.log(
            that.getTop(element), that.getLeft(element) ,
            that.getAllHeight(element), that.getAllWidth(element),
            that.getContainerHeight(), that.getContainerWidth()
        );

        let executeCheck = function (element) {
            if(that.getTop(element) + that.getAllHeight(element) >= that.getContainerHeight()){
                Log.log('body碰撞down生效, 回调执行');
                return callback?callback():false;
            }
            if(that.getTop(element) <= 0){
                Log.log('body碰撞生效top(边界外), 回调执行');
                return callback?callback():false;
            }
            if(that.getLeft(element) + that.getAllWidth(element) >= that.getContainerWidth()){
                Log.log('body碰撞right生效, 回调执行');
                return callback?callback():false;
            }
            if(that.getLeft(element) <= 0){
                Log.log('body碰撞left生效(边界外), 回调执行');
                return callback?callback():false;
            }
        }
        //多个
        if(element.length>1){
            $(element).each(function (a, b) {
                executeCheck(b);
            });
            return true;
        }
        //单个
        executeCheck(element);
        return true;
    }
    /**
     * 边界碰撞
     * 使用场景：当容器宽高与窗口宽高一致时调用
     * @param element 源元素
     * @param callback
     * @returns {*}
     */
    detectBody(element, callback){
        let that = this;
        Log.log(
            that.getTop(element), that.getLeft(element) ,
            that.getAllHeight(element), that.getAllWidth(element),
            that.getWindowHeight(), that.getWindowWidth()
        );

        let executeCheck = function (element) {
            if(that.getTop(element) + that.getAllHeight(element) >= that.getWindowHeight()){
                Log.log('body碰撞down生效, 回调执行');
                return callback?callback():false;
            }
            if(that.getTop(element) <= 0){
                Log.log('body碰撞生效top(边界外), 回调执行');
                return callback?callback():false;
            }
            if(that.getLeft(element) + that.getAllWidth(element) >= that.getWindowWidth()){
                Log.log('body碰撞right生效, 回调执行');
                return callback?callback():false;
            }
            if(that.getLeft(element) <= 0){
                Log.log('body碰撞left生效(边界外), 回调执行');
                return callback?callback():false;
            }
        }
        //多个
        if(element.length>1){
            $(element).each(function (a, b) {
                executeCheck(b);
            });
            return true;
        }
        //单个
        executeCheck(element);
        return true;
    }


    /**
     *
     * @param element
     * @private
     */
    _checkElementAttr(element){
        if(!element) throw new Error('源对象不存在');

        if(!this.getTop(element)) throw new Error('源对象top属性不存在');
        if(!this.getLeft(element)) throw new Error('源对象left属性不存在');

    }

    /**
     *
     * @param toElement
     * @private
     */
    _checkToElementAttr(toElement){
        if(toElement) {
            if(!this.getTop(toElement)) throw new Error('目标对象top属性不存在');
            if(!this.getLeft(toElement)) throw new Error('目标对象left属性不存在');
        }
    }

    /**
     * 数学碰撞
     * @param rectangle1 碰撞体1
     * @param rectangle2 碰撞体2
     * @param callback 碰撞回调(碰撞后，要完成的其它业务逻辑)
     * @returns {boolean} 返回结果无实际参考作用
     */
    mathCrash(rectangle1, rectangle2, callback){
        let that = this;
        Log.log(
            rectangle1,
            rectangle2,
        );
        if(callback && typeof callback != 'function') throw new Error('回调函数类型错误');
        if(!$(rectangle1).length) throw new Error('源元素不存在');
        if(!$(rectangle2).length) throw new Error('目标元素不存在');
        //碰撞体双多情况(扩展)
        if(that.getLength(rectangle1)>1 && that.getLength(rectangle2)>1){


            return true;
        }
        //碰撞体非单一情况1
        if(that.getLength(rectangle1)>1 && that.getLength(rectangle2)===1){
            let rectangle2Obj = {
                x: that.getLeft(rectangle2),
                y: that.getTop(rectangle2),
                width: that.getAllWidth(rectangle2),
                height: that.getAllHeight(rectangle2),
            };
            let rectangle1Obj = null;
            $(rectangle1).each(function (a, b) {
                rectangle1Obj = {
                    x: that.getLeft(b),
                    y: that.getTop(b),
                    width: that.getAllWidth(b),
                    height: that.getAllHeight(b),
                };
                if(that.isOverlap(rectangle1Obj, rectangle2Obj)){
                    Log.log('碰撞生效,碰撞体非单一情况1');
                    callback();
                }
            });
            return true;
        }
        //碰撞体非单一情况2
        if(that.getLength(rectangle1)===1 && that.getLength(rectangle2)>1){
            let rectangle1Obj = {
                x: that.getLeft(rectangle1),
                y: that.getTop(rectangle1),
                width: that.getAllWidth(rectangle1),
                height: that.getAllHeight(rectangle1),
            };
            let rectangle2Obj = null;
            $(rectangle2).each(function (a, b) {
                rectangle2Obj = {
                    x: that.getLeft(b),
                    y: that.getTop(b),
                    width: that.getAllWidth(b),
                    height: that.getAllHeight(b),
                };
                if(that.isOverlap(rectangle1Obj, rectangle2Obj)){
                    Log.log('碰撞生效,碰撞体非单一情况2');
                    callback();
                }
            });
            return true;
        }
        //单一情况
        let rectangle1Obj = {
            x: that.getLeft(rectangle1),
            y: that.getTop(rectangle1),
            width: that.getAllWidth(rectangle1),
            height: that.getAllHeight(rectangle1),
        };
        let rectangle2Obj = {
            x: that.getLeft(rectangle2),
            y: that.getTop(rectangle2),
            width: that.getAllWidth(rectangle2),
            height: that.getAllHeight(rectangle2),
        };
        if(that.isOverlap(rectangle1Obj, rectangle2Obj)){
            Log.log('碰撞生效,单一情况');
            callback();
        }
        return true;
    }

    /**
     * 碰撞计算
     * @param element 友方单位(本体单位,如子弹，炮弹，技能，特效)
     * @param toElements 敌方单位元素
     * @param callback 碰撞后执行回调
     */
    crash(element, toElements, callback) {
        let that = this;
        if(element.length>1) throw new Error('碰撞这一刻,友方运动单位只能有一个');
        let pos = that.getPosition(element);
        let direction = that.getDirection(element);//方位
        let friend_height = that.getAllHeight(element);//高度
        let friend_width = that.getAllWidth(element);//宽度
        //友方单位本体范围
        let friendScope = {
            'top':pos.top,
            'left':pos.left,
            'topheigth':pos.top+that.getAllHeight(element),
            'leftwidth':pos.left+that.getAllWidth(element),
        };

        //友方单位飞行：方位上下左右
        if(direction === 'top'){
            //循环障碍物
            $(toElements).each(function (a, b) {
                //为了便于调试，需要将友方单位飞行速度调慢
                if(
                    (friendScope.top <= (that.getTop(b)+that.getAllHeight(b))
                        && friendScope.left <= (that.getLeft(b)+that.getAllWidth(b))
                        && friendScope.leftwidth >= (that.getLeft(b))
                        && friendScope.top >= (that.getTop(b))
                    )
                ){
                    //碰撞
                    Log.log('碰撞生效');
                    callback();
                }

            });
        }else if(direction === 'down'){
            //循环障碍物
            $(toElements).each(function (a, b) {
                //为了便于调试，需要将友方单位飞行速度调慢
                if(
                    (friendScope.topheigth >= (that.getTop(b))
                        && friendScope.left <= (that.getLeft(b)+that.getAllWidth(b))
                        && friendScope.leftwidth >= (that.getLeft(b))
                        && friendScope.topheigth <= (that.getTop(b)+that.getAllHeight(b))
                    )
                ){
                    //碰撞
                    Log.log('碰撞生效');
                    callback();
                }

            });

        }else if(direction === 'left'){
            //循环障碍物
            $(toElements).each(function (a, b) {
                //为了便于调试，需要将友方单位飞行速度调慢
                if(
                    friendScope.left <= (that.getLeft(b)+that.getAllWidth(b))
                    && friendScope.top <= (that.getTop(b)+that.getAllHeight(b))
                    && friendScope.top+friend_height >= (that.getTop(b))
                    && friendScope.left >= (that.getLeft(b))

                ){
                    //碰撞
                    Log.log('碰撞生效');
                    callback();
                }

            });

        }else if(direction === 'right'){
            //循环障碍物
            $(toElements).each(function (a, b) {
                //为了便于调试，需要将友方单位飞行速度调慢
                if(
                    friendScope.left+friend_width >= (that.getLeft(b))
                    && friendScope.top+friend_height >= (that.getTop(b))
                    && friendScope.top <= (that.getTop(b)+that.getAllHeight(b))
                    && friendScope.left <= (that.getLeft(b)+that.getAllWidth(b))
                ){
                    //碰撞
                    Log.log('碰撞生效');
                    callback();
                }

            });

        }


    }






    // /**
    //  * 边界碰撞，执行碰撞结果
    //  */
    // checkDocBoundary (ele, rollBack) {
    //     var is_end = true;
    //     var pos = $(ele).position();
    //     if(pos.left < 0){
    //         is_end = false;
    //     }
    //     if(pos.top < 0){
    //         is_end = false;
    //     }
    //     if(pos.left*1+$(ele).width() >= CommonOption.doc_width){
    //         is_end = false;
    //     }
    //     if(pos.top*1+$(ele).height() >= CommonOption.doc_height){
    //         is_end = false;
    //     }
    //     if(false === is_end){
    //         Runtime.setLog('与边界碰撞，开始执行碰撞回调');
    //         this.checkRollBack(rollBack);
    //     }
    // }
    // //边界碰撞后
    // bumpBoundaryAfter () {
    //     if(typeof this.bumpAfterAction != 'function')
    //         Error.throwVarIsNotFunctionError('边界碰撞后,页面缺少:bumpAfterAction函数');
    //     //自定义边界碰撞后的操作,交由开发者决定,
    //     //同时你的页面需要定义一个JavaScript bumpAfterAction函数来被系统调用
    //     this.bumpAfterAction();
    // }
    // //覆盖即可
    // bumpAfterAction () {
    //
    // }
}